package com.titan.core.utils.file;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.titan.core.utils.comm.SocketUtils;
import com.titan.core.utils.data.FormatUtils;

/**
 * @author 周成功
 * @email 86898837@qq.com
 * @date 2020年02月10日
 */
public class JsonUtils {
    private static ObjectMapper mapper = null;
    static {
        mapper = new ObjectMapper();
        mapper.disable(SerializationFeature.WRAP_ROOT_VALUE);
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        mapper.disable(MapperFeature.DEFAULT_VIEW_INCLUSION);
        mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
        // 允许单引号
        mapper.enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES);
    }
    
    public static String toString(Object src) throws Exception {
        String json = mapper.writeValueAsString(src);
        return json;
    }    
    
    public static <T> T toObject(String json, Class<T> classOfT) throws Exception {
        if(StringUtils.isEmpty(json) || classOfT==null) {
            return null;
        }
        return mapper.readValue(json, classOfT);
    }    
    
    public static Map<String,String> toMapString(String json) throws Exception {
        Map<?,?> map = JsonUtils.toObject(json, Map.class);
        Map<String,String> result = new HashMap<String,String>();
        if(map==null || map.size()==0) {
            return result;
        }
        Iterator<?> iterator = map.keySet().iterator();
        while(iterator.hasNext()) {
            Object key = iterator.next();
            Object value = map.get(key);
            result.put(FormatUtils.toString(key), FormatUtils.toString(value));
        }       
        return result;
    }
    public static Map<String,Object> toMapKeyString(String json) throws Exception {
        Map<?,?> map = JsonUtils.toObject(json, Map.class);
        Map<String,Object> result = new HashMap<String,Object>();
        if(map==null || map.size()==0) {
            return result;
        }
        Iterator<?> iterator = map.keySet().iterator();
        while(iterator.hasNext()) {
            Object key = iterator.next();
            Object value = map.get(key);
            result.put(FormatUtils.toString(key), value);
        }       
        return result;
    }   
    
    
    public static String toObjectString(String k01, Object v01) {
        return toObjectJson(k01, v01);
    }
    public static String toObjectString(String k01, Object v01, String k02, Object v02) {
        return toObjectJson(k01, v01, k02, v02);
    }
    public static String toObjectString(String k01, Object v01, String k02, Object v02, String k03, Object v03) {
        return toObjectJson(k01, v01, k02, v02, k03, v03);
    }
    public static String toObjectString(String k01, Object v01, String k02, Object v02, String k03, Object v03, String k04, Object v04) {
        return toObjectJson(k01, v01, k02, v02, k03, v03, k04, v04);
    }
    public static String toObjectString(String k01, Object v01, String k02, Object v02, String k03, Object v03, String k04, Object v04, String k05, Object v05) {
        return toObjectJson(k01, v01, k02, v02, k03, v03, k04, v04, k05, v05);
    }
    public static String toObjectString(String k01, Object v01, String k02, Object v02, String k03, Object v03, String k04, Object v04, String k05, Object v05, String k06, Object v06) {
        return toObjectJson(k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06);
    }
    public static String toObjectString(String k01, Object v01, String k02, Object v02, String k03, Object v03, String k04, Object v04, String k05, Object v05, String k06, Object v06, String k07, Object v07) {
        return toObjectJson(k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07);
    }
    public static String toObjectString(String k01, Object v01, String k02, Object v02, String k03, Object v03, String k04, Object v04, String k05, Object v05, String k06, Object v06, String k07, Object v07, String k08, Object v08) {
        return toObjectJson(k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08);
    }
    public static String toObjectString(String k01, Object v01, String k02, Object v02, String k03, Object v03, String k04, Object v04, String k05, Object v05, String k06, Object v06, String k07, Object v07, String k08, Object v08, String k09, Object v09) {
        return toObjectJson(k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09);
    }
    public static String toObjectString(String k01, Object v01, String k02, Object v02, String k03, Object v03, String k04, Object v04, String k05, Object v05, String k06, Object v06, String k07, Object v07, String k08, Object v08, String k09, Object v09, String k10, Object v10) {
        return toObjectJson(k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09, k10, v10);
    }
    public static String toObjectString(String k01, Object v01, String k02, Object v02, String k03, Object v03, String k04, Object v04, String k05, Object v05, String k06, Object v06, String k07, Object v07, String k08, Object v08, String k09, Object v09, String k10, Object v10, String k11, Object v11) {
        return toObjectJson(k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09, k10, v10, k11, v11);
    }
    public static String toObjectString(String k01, Object v01, String k02, Object v02, String k03, Object v03, String k04, Object v04, String k05, Object v05, String k06, Object v06, String k07, Object v07, String k08, Object v08, String k09, Object v09, String k10, Object v10, String k11, Object v11, String k12, Object v12) {
        return toObjectJson(k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09, k10, v10, k11, v11, k12, v12);
    }
    public static String toObjectString(String k01, Object v01, String k02, Object v02, String k03, Object v03, String k04, Object v04, String k05, Object v05, String k06, Object v06, String k07, Object v07, String k08, Object v08, String k09, Object v09, String k10, Object v10, String k11, Object v11, String k12, Object v12, String k13, Object v13) {
        return toObjectJson(k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09, k10, v10, k11, v11, k12, v12, k13, v13);
    }
    public static String toObjectString(String k01, Object v01, String k02, Object v02, String k03, Object v03, String k04, Object v04, String k05, Object v05, String k06, Object v06, String k07, Object v07, String k08, Object v08, String k09, Object v09, String k10, Object v10, String k11, Object v11, String k12, Object v12, String k13, Object v13, String k14, Object v14) {
        return toObjectJson(k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14);
    }
    public static String toObjectString(String k01, Object v01, String k02, Object v02, String k03, Object v03, String k04, Object v04, String k05, Object v05, String k06, Object v06, String k07, Object v07, String k08, Object v08, String k09, Object v09, String k10, Object v10, String k11, Object v11, String k12, Object v12, String k13, Object v13, String k14, Object v14, String k15, Object v15) {
        return toObjectJson(k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15);
    }
    public static String toObjectString(String k01, Object v01, String k02, Object v02, String k03, Object v03, String k04, Object v04, String k05, Object v05, String k06, Object v06, String k07, Object v07, String k08, Object v08, String k09, Object v09, String k10, Object v10, String k11, Object v11, String k12, Object v12, String k13, Object v13, String k14, Object v14, String k15, Object v15, String k16, Object v16) {
        return toObjectJson(k01, v01, k02, v02, k03, v03, k04, v04, k05, v05, k06, v06, k07, v07, k08, v08, k09, v09, k10, v10, k11, v11, k12, v12, k13, v13, k14, v14, k15, v15, k16, v16);
    }
    public static String toObjectString(Object...items) {
        return toObjectJson(items);
    }
    private static String toObjectJson(Object...items) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        JsonGenerator jGenerator = null;
        try {
            JsonFactory jfactory = new JsonFactory();  
            jGenerator = jfactory.createGenerator(out, JsonEncoding.UTF8);
            jGenerator.writeStartObject();
            
            int len = items.length;
            for (int i = 0; i < len; i=i+2) {
                if(items[i]==null) {
                    continue;
                }
                build(jGenerator, FormatUtils.toString(items[i]), items[i+1]);
            }
            jGenerator.writeEndObject();
            jGenerator.flush();
            return out.toString();
        } catch(IOException e) {
            throw new RuntimeException(e);
        } finally {
            SocketUtils.closeQuietly(jGenerator);
            SocketUtils.closeQuietly(out);
        }
    }
    private static void build(JsonGenerator jGenerator, String key, Object value) throws IOException {
        if( StringUtils.isEmpty(key) || value==null ) {
            return;
        }
        jGenerator.writeFieldName(key);
        build(jGenerator, value);
    }
    public static String toArrayString(Object...items) {
        if( items==null || items.length==0 ) {
            return "[]";
        }
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        JsonGenerator jGenerator = null;
        try {
            JsonFactory jfactory = new JsonFactory();  
            jGenerator = jfactory.createGenerator(out, JsonEncoding.UTF8);
            if( items.length==1 ) {
                Object value = items[0];
                if( value instanceof boolean[]
                        || value instanceof byte[]
                        || value instanceof char[]
                        || value instanceof short[]
                        || value instanceof int[]
                        || value instanceof long[]
                        || value instanceof float[]
                        || value instanceof double[]
                        || value.getClass().isArray()
                        || value instanceof Collection<?>
                        || value instanceof Map<?, ?>
                        ) {
                    build(jGenerator, value);
                } else {
                    jGenerator.writeStartArray();
                    build(jGenerator, value);
                    jGenerator.writeEndArray();
                }
            } else {
                jGenerator.writeStartArray();
                for (int i = 0; i < items.length; i++) {
                    build(jGenerator, items[i]);
                }
                jGenerator.writeEndArray();
            }
            jGenerator.flush();
            return out.toString();
        } catch(IOException e) {
            throw new RuntimeException(e);
        } finally {
            SocketUtils.closeQuietly(jGenerator);
            SocketUtils.closeQuietly(out);
        }
    }
    private static void build(JsonGenerator jGenerator, Object value) throws IOException {
        if( value==null ) {
            jGenerator.writeNull();
        } else if((value instanceof Float)) {
            jGenerator.writeNumber( (Float)value );
        } else if((value instanceof Double)) {
            jGenerator.writeNumber( (Double)value );
        } else if((value instanceof Byte)) {
            jGenerator.writeNumber( (Byte)value );
        } else if((value instanceof Short)) {
            jGenerator.writeNumber( (Short)value );
        } else if((value instanceof Integer)) {
            jGenerator.writeNumber( (Integer)value );
        } else if((value instanceof Long)) {
            jGenerator.writeNumber( (Long)value );
        } else if((value instanceof Boolean)) {
            jGenerator.writeBoolean( (Boolean)value );
        } else if( value instanceof java.lang.String
                || value instanceof java.lang.Character
                || value instanceof java.lang.StringBuffer
                || value instanceof java.lang.StringBuilder
                ) {
            jGenerator.writeString( FormatUtils.toString(value) );
        } else if( value instanceof java.util.Date
                || value instanceof java.util.Calendar
                || value instanceof java.sql.Timestamp
                ) {
            jGenerator.writeString( FormatUtils.toString(value, "yyyy-MM-dd HH:mm:ss", StringUtils.EMPTY) );
        } else if(value instanceof java.math.BigDecimal) {
            jGenerator.writeNumber( (java.math.BigDecimal)value );
        } else if((value instanceof java.math.BigInteger)) {
            jGenerator.writeNumber( (java.math.BigInteger)value );
        } else if( value instanceof boolean[] ) {
            jGenerator.writeStartArray();
            boolean[] array = (boolean[])value;
            for (int i = 0; i < array.length; i++) {
                jGenerator.writeBoolean( array[i] );
            }
            jGenerator.writeEndArray();
        } else if( value instanceof byte[] ) {
            jGenerator.writeStartArray();
            byte[] array = (byte[])value;
            for (int i = 0; i < array.length; i++) {
                jGenerator.writeNumber( array[i] );
            }
            jGenerator.writeEndArray();
        } else if( value instanceof char[] ) {
            jGenerator.writeStartArray();
            char[] array = (char[])value;
            for (int i = 0; i < array.length; i++) {
                jGenerator.writeString( FormatUtils.toString(array[i]) );
            }
            jGenerator.writeEndArray();
        } else if( value instanceof short[] ) {
            jGenerator.writeStartArray();
            short[] array = (short[])value;
            for (int i = 0; i < array.length; i++) {
                jGenerator.writeNumber( array[i] );
            }
            jGenerator.writeEndArray();
        } else if( value instanceof int[] ) {
            jGenerator.writeStartArray();
            int[] array = (int[])value;
            for (int i = 0; i < array.length; i++) {
                jGenerator.writeNumber( array[i] );
            }
            jGenerator.writeEndArray();
        } else if( value instanceof long[] ) {
            jGenerator.writeStartArray();
            long[] array = (long[])value;
            for (int i = 0; i < array.length; i++) {
                jGenerator.writeNumber( array[i] );
            }
            jGenerator.writeEndArray();
        } else if( value instanceof float[] ) {
            jGenerator.writeStartArray();
            float[] array = (float[])value;
            for (int i = 0; i < array.length; i++) {
                jGenerator.writeNumber( array[i] );
            }
            jGenerator.writeEndArray();
        } else if( value instanceof double[] ) {
            jGenerator.writeStartArray();
            double[] array = (double[])value;
            for (int i = 0; i < array.length; i++) {
                jGenerator.writeNumber( array[i] );
            }
            jGenerator.writeEndArray();
        } else if( value.getClass().isArray() ) {
            jGenerator.writeStartArray();
            Object[] array = (Object[])value;
            for (int i = 0; i < array.length; i++) {
                build(jGenerator, array[i]);
            }
            jGenerator.writeEndArray();
        } else if(value instanceof Collection<?>) {
            Collection<?> array = (Collection<?>)value;
            Iterator<?> iterator = array.iterator();
            
            jGenerator.writeStartArray();
            while(iterator.hasNext()) {
                build(jGenerator, iterator.next());
            }
            jGenerator.writeEndArray();
        } else if(value instanceof Map<?, ?>) {
            Map<?, ?> map = (Map<?, ?>)value;
            Iterator<?> iterator = map.keySet().iterator();

            jGenerator.writeStartObject();
            while(iterator.hasNext()) {
                String key = FormatUtils.toString(iterator.next());
                build(jGenerator, key, map.get(key));
            }
            jGenerator.writeEndObject();
        } else {
            jGenerator.writeString( FormatUtils.toString(value) );
        }
    }    
    
}
